home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Utilities / LinkList.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  16.1 KB  |  666 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkList.cpp
  3.  
  4.     Contains:    Primitive linked list class
  5.  
  6.     Owned by:    Richard Rodseth, Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #ifndef _LINKLIST_
  13. #include "LinkList.h"
  14. #endif
  15.  
  16. #ifndef _EXCEPT_
  17. #include "Except.h"
  18. #endif
  19.  
  20. #ifndef __ERRORS__
  21. #include <Errors.h>
  22. #endif
  23.  
  24. #ifndef _ODDEBUG_
  25. #include "ODDebug.h"
  26. #endif
  27.  
  28. #ifndef _UTILERRS_
  29. #include "UtilErrs.h"
  30. #endif
  31.  
  32. #pragma segment ODLinkedList
  33.  
  34. //==============================================================================
  35. // Constants
  36. //==============================================================================
  37.  
  38. //==============================================================================
  39. // Scalar Types
  40. //==============================================================================
  41.  
  42. //==============================================================================
  43. // Local Classes
  44. //==============================================================================
  45.  
  46. //==============================================================================
  47. // Global Variables
  48. //==============================================================================
  49.  
  50. //==============================================================================
  51. // Function Prototype
  52. //==============================================================================
  53.  
  54.  
  55. //==============================================================================
  56. // Link
  57. //==============================================================================
  58.  
  59.  
  60.  
  61. // Many of the simple link methods are inlines; see List.h for implementations.
  62.  
  63.  
  64. //------------------------------------------------------------------------------
  65. // Link::Link
  66. //
  67. // Constructor for Link
  68. //------------------------------------------------------------------------------
  69.  
  70. Link::Link()                            
  71.     fNext = kODNULL; 
  72.     fPrevious = kODNULL;
  73. }
  74.  
  75. //------------------------------------------------------------------------------
  76. // Link::Link
  77. //
  78. // Constructor for Link
  79. //------------------------------------------------------------------------------
  80.  
  81. Link::Link(Link* next, Link* previous)                            
  82.     fNext = next; 
  83.     fPrevious = previous;
  84. }
  85.  
  86. //------------------------------------------------------------------------------
  87. // Link::Link
  88. //
  89. // Copy constructor for Link
  90. //------------------------------------------------------------------------------
  91.  
  92. Link::Link( const Link &link )                            
  93.     fNext = link.fNext; 
  94.     fPrevious = link.fPrevious;
  95. }
  96.  
  97. //------------------------------------------------------------------------------
  98. // Link::Link
  99. //
  100. // Destructor for Link
  101. //------------------------------------------------------------------------------
  102.  
  103. Link::~Link()                                            
  104. {
  105. }
  106.  
  107. //------------------------------------------------------------------------------
  108. // Link::Remove
  109. //
  110. // Remove a link from its list (if any). DO NOT call this directly if there are
  111. // any iterators active on the list; use LinkedList::Remove instead.
  112. //------------------------------------------------------------------------------
  113.  
  114. void    Link::Remove( )
  115. {
  116.     if( fPrevious )
  117.         fPrevious->SetNext(fNext);
  118.     if( fNext )
  119.         fNext->SetPrevious(fPrevious);
  120.     fNext = kODNULL;
  121.     fPrevious = kODNULL;
  122. }
  123.  
  124. //------------------------------------------------------------------------------
  125. // Link::AddBefore
  126. //
  127. // Add a link to a list before another link. It must not already be on any list.
  128. // DO NOT call this directly if there are any iterators active on the list;
  129. // use LinkedList::Remove instead.
  130. //------------------------------------------------------------------------------
  131.  
  132. void    Link::AddBefore( Link *link )
  133. {
  134.     ASSERT(link!=kODNULL,paramErr);
  135.     WASSERT(fNext==kODNULL);
  136.     WASSERT(fPrevious==kODNULL);
  137.     fNext = link;
  138.     fPrevious = link->GetPrevious();
  139.     fPrevious->SetNext(this);
  140.     fNext->SetPrevious(this);
  141. }
  142.  
  143. //------------------------------------------------------------------------------
  144. // Link::AddAfter
  145. //
  146. // Add a link to a list after another link. It must not already be on any list.
  147. // DO NOT call this directly if there are any iterators active on the list;
  148. // use LinkedList::Remove instead.
  149. //------------------------------------------------------------------------------
  150.  
  151. void    Link::AddAfter( Link *link )
  152. {
  153.     ASSERT(link!=kODNULL,paramErr);
  154.     WASSERT(fNext==kODNULL);
  155.     WASSERT(fPrevious==kODNULL);
  156.     fPrevious = link;
  157.     fNext = link->GetNext();
  158.     fPrevious->SetNext(this);
  159.     fNext->SetPrevious(this);
  160. }
  161.  
  162. //======================================================================================
  163. // Class LinkedList
  164. //======================================================================================
  165.  
  166. //------------------------------------------------------------------------------
  167. // LinkedList::LinkedList
  168. //
  169. // Constructor for LinkedList
  170. //------------------------------------------------------------------------------
  171.  
  172. LinkedList::LinkedList()
  173.     :fSentinel(&fSentinel,&fSentinel),
  174.      fSeed(0)
  175. {
  176. }
  177.  
  178. //------------------------------------------------------------------------------
  179. // LinkedList::~LinkedList
  180. //
  181. // Destructor for LinkedList
  182. //------------------------------------------------------------------------------
  183.  
  184. LinkedList::~LinkedList()
  185. {
  186.     // The list does NOT delete all its links!
  187. }
  188.  
  189. //------------------------------------------------------------------------------
  190. // LinkedList::IsEmpty
  191. //
  192. // Description
  193. //------------------------------------------------------------------------------
  194.  
  195. ODBoolean LinkedList::IsEmpty() const
  196. {
  197.     return this->IsSentinel( fSentinel.GetNext() );
  198. }
  199.  
  200. //------------------------------------------------------------------------------
  201. // LinkedList::Count
  202. //
  203. // Description
  204. //------------------------------------------------------------------------------
  205.  
  206. ODULong LinkedList::Count() const
  207. {
  208.     Link* l = fSentinel.GetNext();
  209.     ODULong count = 0;
  210.     while (this->NotSentinel(l))
  211.     {
  212.         count++;
  213.         l = l->GetNext();
  214.         ASSERT(l!=kODNULL,kODErrAssertionFailed);
  215.     }
  216.     return count;
  217. }
  218.  
  219. //------------------------------------------------------------------------------
  220. // LinkedList::Includes
  221. //
  222. // Does the list include a particular link?
  223. //------------------------------------------------------------------------------
  224.  
  225. ODBoolean LinkedList::Includes( const Link *link ) const
  226. {
  227.     Link* l = fSentinel.GetNext();
  228.     while (this->NotSentinel(l))
  229.     {
  230.         if( l == link )
  231.             return kODTrue;
  232.         else
  233.             l = l->GetNext();
  234.     }
  235.     return kODFalse;
  236. }
  237.  
  238. //------------------------------------------------------------------------------
  239. // LinkedList::DeleteAllLinks
  240. //
  241. // Description
  242. //------------------------------------------------------------------------------
  243.  
  244. void    LinkedList::DeleteAllLinks()
  245. {
  246.  
  247.     Link* l = fSentinel.GetNext();
  248.     Link* n = l;
  249.     while (this->NotSentinel(n))
  250.     {
  251.         n = l->GetNext();
  252.         delete l;    
  253.         l = n;
  254.     }
  255.     fSentinel.SetNext(&fSentinel);
  256.     fSentinel.SetPrevious(&fSentinel);
  257.     fSeed++;
  258. }
  259.  
  260. //------------------------------------------------------------------------------
  261. // LinkedList::RemoveAll
  262. //
  263. // Description
  264. //------------------------------------------------------------------------------
  265.  
  266. void    LinkedList::RemoveAll()
  267. {
  268.  
  269.     Link* l = fSentinel.GetNext();
  270.     Link* n = l;
  271.     while (this->NotSentinel(l))
  272.     {
  273.         n = l->GetNext();
  274.         l->SetNext(kODNULL);
  275.         l->SetPrevious(kODNULL);
  276.         l = n;
  277.     }
  278.     fSentinel.SetNext(&fSentinel);
  279.     fSentinel.SetPrevious(&fSentinel);
  280. }
  281.  
  282. //------------------------------------------------------------------------------
  283. // LinkedList::Remove
  284. //
  285. // Description
  286. //------------------------------------------------------------------------------
  287.  
  288. void    LinkedList::Remove(Link& aLink)
  289. {
  290.     fSeed++;
  291.     aLink.Remove();
  292. }
  293.  
  294. //------------------------------------------------------------------------------
  295. // LinkedList::RemoveFirst
  296. //
  297. // Description
  298. //------------------------------------------------------------------------------
  299.  
  300. Link* LinkedList::RemoveFirst()
  301. {
  302.     Link* old = fSentinel.GetNext();
  303.     if (this->NotSentinel(old))
  304.     {
  305.         fSeed++;
  306.         old->Remove();
  307.         return old;
  308.     }
  309.     else
  310.     {
  311.         return kODNULL;
  312.     }
  313. }
  314.  
  315. //------------------------------------------------------------------------------
  316. // LinkedList::RemoveLast
  317. //
  318. // Description
  319. //------------------------------------------------------------------------------
  320.  
  321. Link* LinkedList::RemoveLast()
  322. {
  323.     Link* old = fSentinel.GetPrevious();
  324.     if (this->NotSentinel(old))
  325.     {
  326.         fSeed++;
  327.         old->Remove();
  328.         return old;
  329.     }
  330.     else
  331.     {
  332.         return kODNULL;
  333.     }
  334. }
  335.  
  336. //------------------------------------------------------------------------------
  337. // LinkedList::AddFirst
  338. //
  339. // Description
  340. //------------------------------------------------------------------------------
  341.  
  342. void    LinkedList::AddFirst(Link* link)
  343. {
  344.     link->AddAfter(this->GetSentinel());
  345.     fSeed++;
  346. }
  347.  
  348. //------------------------------------------------------------------------------
  349. // LinkedList::AddLast( Link )
  350. //
  351. // Description
  352. //------------------------------------------------------------------------------
  353.  
  354. void    LinkedList::AddLast(Link* link)
  355. {
  356.     link->AddBefore(this->GetSentinel());
  357.     fSeed++;
  358. }
  359.  
  360. //------------------------------------------------------------------------------
  361. // LinkedList::AddLast( LinkedList )
  362. //
  363. // Append contents of another list to my end. (Other list becomes empty.)
  364. //------------------------------------------------------------------------------
  365.  
  366. void    LinkedList::AddLast( LinkedList &list )
  367. {
  368.     if( !list.IsEmpty() ) {
  369.         Link *myLast = fSentinel.GetPrevious();
  370.         Link *itsFirst = list.First();
  371.         myLast->SetNext(itsFirst);
  372.         itsFirst->SetPrevious(myLast);
  373.         
  374.         Link *itsLast = list.Last();
  375.         itsLast->SetNext(this->GetSentinel());
  376.         fSentinel.SetPrevious(itsLast);
  377.         
  378.         list.fSentinel.SetNext(this->GetSentinel());
  379.         list.fSentinel.SetPrevious(this->GetSentinel());
  380.  
  381.         fSeed++;
  382.         list.fSeed++;
  383.     }
  384. }
  385.  
  386. //------------------------------------------------------------------------------
  387. // LinkedList::AddLastUnique( LinkedList )
  388. //
  389. // Append contents of another list (w/o duplication) to my end.
  390. //------------------------------------------------------------------------------
  391.  
  392. void    LinkedList::AddLastUnique( LinkedList &list )
  393. {
  394.     for( Link *link = fSentinel.GetNext(); this->NotSentinel(link); link=link->GetNext() )
  395.         if( list.Includes(link) )
  396.             list.Remove(*link);
  397.     this->AddLast(list);
  398. }
  399.  
  400. //------------------------------------------------------------------------------
  401. // LinkedList::AddBefore
  402. //
  403. // Description
  404. //------------------------------------------------------------------------------
  405.  
  406. void LinkedList::AddBefore(Link& existing, Link* link)
  407. {
  408.     link->AddBefore(&existing);
  409.     fSeed++;
  410. }
  411.  
  412. //------------------------------------------------------------------------------
  413. // LinkedList::AddAfter
  414. //
  415. // Description
  416. //------------------------------------------------------------------------------
  417.  
  418. void LinkedList::AddAfter(Link& existing, Link* link)
  419. {
  420.     link->AddAfter(&existing);
  421.     fSeed++;
  422. }
  423.  
  424. //------------------------------------------------------------------------------
  425. // LinkedList::After
  426. //
  427. // Description
  428. //------------------------------------------------------------------------------
  429.  
  430. Link* LinkedList::After(const Link& link) const
  431. {
  432.     Link *next = link.GetNext();
  433.     if( this->IsSentinel(next) )
  434.         return kODNULL;
  435.     else
  436.         return next;
  437. }
  438.  
  439. //------------------------------------------------------------------------------
  440. // LinkedList::Before
  441. //
  442. // Description
  443. //------------------------------------------------------------------------------
  444.  
  445. Link* LinkedList::Before(const Link& link) const
  446. {
  447.     Link *prev = link.GetPrevious();
  448.     if( this->IsSentinel(prev) )
  449.         return kODNULL;
  450.     else
  451.         return prev;
  452. }
  453.  
  454. //------------------------------------------------------------------------------
  455. // LinkedList::First
  456. //
  457. // Description
  458. //------------------------------------------------------------------------------
  459.  
  460. Link*    LinkedList::First()  const
  461. {
  462.     return this->NotSentinel(fSentinel.GetNext()) ? fSentinel.GetNext() : (Link*) kODNULL;
  463. }
  464.  
  465. //------------------------------------------------------------------------------
  466. // LinkedList::Last
  467. //
  468. // Description
  469. //------------------------------------------------------------------------------
  470.  
  471. Link* LinkedList::Last() const
  472. {
  473.     return this->NotSentinel(fSentinel.GetPrevious()) ? fSentinel.GetPrevious() : (Link*) kODNULL;
  474. }
  475.  
  476.  
  477. //======================================================================================
  478. // Class LinkedListIterator
  479. //======================================================================================
  480.  
  481. //------------------------------------------------------------------------------
  482. // LinkedListIterator::LinkedListIterator
  483. //
  484. // Constructor for LinkedListIterator
  485. //------------------------------------------------------------------------------
  486.  
  487. LinkedListIterator::LinkedListIterator(LinkedList* list)
  488. {
  489.     fList = list;
  490.     fCurrent = kODNULL;
  491.     fNext = kODNULL;
  492.     fPrevious = kODNULL;
  493.     fSentinel = &list->fSentinel;
  494.     fSeed = fList->fSeed;    
  495. }
  496.  
  497. //------------------------------------------------------------------------------
  498. // LinkedListIterator::~LinkedListIterator
  499. //
  500. // Destructor for LinkedListIterator
  501. //------------------------------------------------------------------------------
  502.  
  503. LinkedListIterator::~LinkedListIterator()
  504. {
  505. }
  506.  
  507. //------------------------------------------------------------------------------
  508. // LinkedListIterator::First
  509. //
  510. // Description
  511. //------------------------------------------------------------------------------
  512.  
  513. Link* LinkedListIterator::First()
  514. {
  515.     if (fList == kODNULL)
  516.         return kODNULL;
  517.         
  518.     if (fSeed != fList->fSeed)
  519.         THROW(kODErrIteratorOutOfSync);
  520.         
  521.     fCurrent = fList->First();
  522.     if (fCurrent == fSentinel)
  523.         fCurrent = kODNULL;
  524.     return fCurrent;
  525. }
  526.  
  527. //------------------------------------------------------------------------------
  528. // LinkedListIterator::Next
  529. //
  530. // Description
  531. //------------------------------------------------------------------------------
  532.  
  533. Link* LinkedListIterator::Next()
  534. {
  535.     if (fList == kODNULL)
  536.         return kODNULL;
  537.  
  538.     if (fSeed != fList->fSeed)
  539.         THROW(kODErrIteratorOutOfSync);
  540.  
  541.     if (fCurrent == kODNULL)
  542.     {
  543.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  544.         {
  545.             return this->First();
  546.         }
  547.         else    // Just deleted
  548.         {
  549.             fCurrent = fNext;
  550.             fPrevious = kODNULL;
  551.             fNext = kODNULL;
  552.         }
  553.     }
  554.     else
  555.         fCurrent = fCurrent->GetNext();
  556.     
  557.     if (fCurrent == fSentinel)
  558.         fCurrent = kODNULL;
  559.     return fCurrent;
  560. }
  561.  
  562. //------------------------------------------------------------------------------
  563. // LinkedListIterator::Last
  564. //
  565. // Description
  566. //------------------------------------------------------------------------------
  567.  
  568. Link* LinkedListIterator::Last()
  569. {
  570.     if (fList == kODNULL)
  571.         return kODNULL;
  572.  
  573.     if (fSeed != fList->fSeed)
  574.         THROW(kODErrIteratorOutOfSync);
  575.  
  576.     fCurrent = fList->Last();
  577.     if (fCurrent == fSentinel)
  578.         fCurrent = kODNULL;
  579.     return fCurrent;
  580. }
  581.  
  582. //------------------------------------------------------------------------------
  583. // LinkedListIterator::Previous
  584. //
  585. // Description
  586. //------------------------------------------------------------------------------
  587.  
  588. Link* LinkedListIterator::Previous()
  589. {
  590.     if (fList == kODNULL)
  591.         return kODNULL;
  592.  
  593.     if (fSeed != fList->fSeed)
  594.         THROW(kODErrIteratorOutOfSync);
  595.  
  596.     if (fCurrent == kODNULL)
  597.     {
  598.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  599.         {
  600.             return this->Last();
  601.         }
  602.         else    // Just deleted
  603.         {
  604.             fCurrent = fPrevious;
  605.             fPrevious = kODNULL;
  606.             fNext = kODNULL;
  607.         }
  608.     }
  609.     else
  610.         fCurrent = fCurrent->GetPrevious();
  611.  
  612.     if (fCurrent == fSentinel)
  613.         fCurrent = kODNULL;
  614.     return fCurrent;
  615. }
  616.  
  617. //------------------------------------------------------------------------------
  618. // LinkedListIterator::Current
  619. //
  620. // Description
  621. //------------------------------------------------------------------------------
  622.  
  623. Link* LinkedListIterator::Current()
  624. {
  625.     return fCurrent;
  626. }
  627.  
  628. //------------------------------------------------------------------------------
  629. // LinkedListIterator::IsNotComplete
  630. //
  631. // Description
  632. //------------------------------------------------------------------------------
  633.  
  634. ODBoolean LinkedListIterator::IsNotComplete()
  635. {
  636.     return (fCurrent != kODNULL);
  637. }
  638.  
  639. //------------------------------------------------------------------------------
  640. // LinkedListIterator::RemoveCurrent
  641. //
  642. // Description
  643. //------------------------------------------------------------------------------
  644.  
  645. void  LinkedListIterator::RemoveCurrent()
  646. {
  647.     if (fList == kODNULL)
  648.         return;
  649.         
  650.     if (fSeed != fList->fSeed)
  651.         THROW(kODErrIteratorOutOfSync);
  652.          
  653.     if (fCurrent != kODNULL)
  654.     {
  655.         fNext = fCurrent->GetNext();
  656.         fPrevious = fCurrent->GetPrevious();
  657.             
  658.         fList->Remove(*fCurrent);
  659.         fCurrent = kODNULL;
  660.         fSeed = fList->fSeed;
  661.     }
  662. }
  663.